const baseLoadOption = {
    backFaceCulling: true,
    skipLevelOfDetail: true,
    baseScreenSpaceError: 256,
    maximumScreenSpaceError: 2, // 数值加大，能让最终成像变模糊
    skipScreenSpaceErrorFactor: 16,
    skipLevels: 1,
    immediatelyLoadDesiredLevelOfDetail: true,
    loadSiblings: false, // 如果为true则不会在已加载完概况房屋后，自动从中心开始超清化房屋
    cullRequestsWhileMoving: true,
    cullRequestsWhileMovingMultiplier: 5, // 值越小能够更快的剔除
    preloadWhenHidden: true,
    preferLeaves: true,
    maximumMemoryUsage: 4096, // 内存分配变小有利于倾斜摄影数据回收，提升性能体验
    progressiveResolutionHeightFraction: 0.2, // 数值偏于0能够让初始加载变得模糊
    dynamicScreenSpaceErrorDensity: 0.5, // 数值加大，能让周边加载变快
    dynamicScreenSpaceErrorFactor: 1, // 不知道起了什么作用没，反正放着吧先
    dynamicScreenSpaceError: false, // 根据测试，有了这个后，会在真正的全屏加载完之后才清晰化房屋
    shadows: Cesium.ShadowMode.DISABLED,
    cullWithChildrenBounds: true,
    distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0.0, 50000),
    maximumNumberOfLoadedTiles: 300000
}



/**
 *
 * @param   viewer          cesium 或 mars3d实例
 * @param   children        3dtiles数据列表（详情参考下方children元素）
 * @param   label           默认为 3dtiles，用于渲染tree控件时的标签显示(可选)
 * @param   id              默认随机生成，用于渲染tree控件(可选)
 * @param   baseOption      加载3dtiles的公共参数，会与 children 每一项进行合并(可选)
 *
 */

 /**
 *
 * 
 * children元素
 * @param   id              唯一标识
 * @param   url             资源地址
 * @param   show            3dtiles 是否显示
 * @param   offsetEast      向东的偏移量(单位m，可选)
 * @param   offsetNorth     向北的偏移量(单位m，可选)
 * @param   offsetHeight    高度偏移量(单位m，可选)
 * @param   label           用于渲染tree控件时的标签显示
 *
 */
export function BQGIS_3DTilesetManager ({children, label = "模型", id = getUUId(), baseOption, viewer}) {
    this.viewer = viewer
    this.id = id
    this.label = label
    this.baseOption = baseOption || baseLoadOption
    this.children = []
    if(children){
        this.init(children)
    }
}



BQGIS_3DTilesetManager.prototype.init = function (children) {
    const keys = this.children.map(item => item.id)
    children.forEach(item => {
        const tile = this.children.find(data => data.id === item.id)
        if(tile){
            const index = keys.findIndex(id => id === item.id)
            keys.splice(index, 1)
            this.upDate(tile, item)
        }else{
            this.add(item)
        }
    })
    console.log(keys)
    keys.forEach(id => {
        this.remove(id)
    })
}


/**
 * 获取当前所有显示的3dtiles的 id
 */
BQGIS_3DTilesetManager.prototype.getShowKeys = function () {
    const data = []
    this.children.forEach(item => {
        if(item.show){
            data.push(item.id)
        }
    });
    return data
}

BQGIS_3DTilesetManager.prototype.flyTo = function (id) {
    const layerData = this.get(id)
    this.viewer.flyTo(layerData.entity)
}

BQGIS_3DTilesetManager.prototype.load3Dtiles = function (option) {
    if(!option.id){
        option.id = getUUId()
    }
    this.setShow(option, option.show)
    if(option.show){
        if(option.offsetEast || option.offsetNorth || option.offsetHeight){
            translate(option, option.tileset)
        }
    }
    return option
}


/**
 *
 * 3dtiles 更改数据
 * 
 * @param   id              id, 用于查找3dtiles
 * @param   url             资源地址
 */
BQGIS_3DTilesetManager.prototype.upDate = function (tileData, option) {
    if(option.url !== tileData.url){
        if(tileData.entity){
            this.viewer.scene.primitives.remove(tileData.entity)
        }
        tileData.entity = null
        tileData.url = option.url
    }
    this.setShow(tileData, option.show)
    if((option.offsetEast != tileData.offsetEast) || (option.offsetNorth != tileData.offsetNorth) || (option.offsetHeight != tileData.offsetHeight)){
        this.setOffset(tileData, option)
    }
    tileData = Object.assign(tileData, option)
}

/**
 *
 * 添加 3dtiles
 * 
 * @param   option    3dtiles数据列表
 * 
 *
 */
BQGIS_3DTilesetManager.prototype.add = function (option) {
    const tilesOption = mergeObj(option, this.baseOption)
    const tileData = this.load3Dtiles(tilesOption)
    this.children.push(tileData)
    return tileData
}

BQGIS_3DTilesetManager.prototype.remove = function (id) {
    const index = this.children.findIndex(item => item.id === id)
    const tileData = this.children[index]
    if(index !== -1){
        if(tileData.entity){
            this.viewer.scene.primitives.remove(tileData.entity)
            tileData.entity = null
        }
        this.children.splice(index, 1)
    }
}

/**
 *
 * 3dtiles 位置偏移
 * 
 * @param   id              id, 用于查找3dtiles
 * @param   offsetEast      向东的偏移
 * @param   offsetNorth     向北的偏移
 * @param   offsetHeight    高度偏移
 */

BQGIS_3DTilesetManager.prototype.deviation = function ({id, offsetEast, offsetNorth, offsetHeight}) {
    const tileData = this.get(id)
    if(tileData){
        this.setOffset(tileData, {offsetEast, offsetNorth, offsetHeight})
    }
}

BQGIS_3DTilesetManager.prototype.setOffset = function (tileData, option) {
    for(let key in option){
        if(key === 'offsetEast' || key === 'offsetNorth' || key === 'offsetHeight') {
            tileData[key] = option[key]
        }
    }
    translate(tileData, tileData.entity)
}

/**
 *
 * 3dtiles 位置偏移
 * 
 * @param   id              id, 用于查找3dtiles
 * @param   offsetEast      向东的偏移
 * @param   offsetNorth     向北的偏移
 * @param   offsetHeight    高度偏移
 */
BQGIS_3DTilesetManager.prototype.setOffset = function (tileData, option) {
    for(let key in option){
        if(key === 'offsetEast' || key === 'offsetNorth' || key === 'offsetHeight') {
            tileData[key] = option[key]
        }
    }
    translate(tileData, tileData.entity)
}

/**
 *
 * 3dtiles 显示隐藏
 * 
 * @param   id              
 * @param   show            显示/隐藏
 */
BQGIS_3DTilesetManager.prototype.show = function ({id, show}) {
    const tileData = this.get(id)
    if(tileData){
        this.setShow(tileData, show)
    }
}


BQGIS_3DTilesetManager.prototype.setShow = function (tileData, show) {
    if(!tileData.entity && show){
        tileData.entity = this.viewer.scene.primitives.add(new Cesium.Cesium3DTileset(tileData))
    }
    if(tileData.entity){
        tileData.entity.show = show
    }
    tileData.show = show
}

/**
 *
 * 获取3ditle数据
 * 
 * @param   id              id, 用于查找3dtiles
 */
BQGIS_3DTilesetManager.prototype.get = function (id) {
    return this.children.find(item => item.id === id)
}



function translate({
    offsetEast,
    offsetNorth,
    offsetHeight
}, tileset) {
    // 设置偏移的经纬度(度)
    // const cartographic = Cesium.Cartographic.fromCartesian(
    //     obj.tileset.boundingSphere.center
    // );
    // const targetCartographic = new Cesium.Cartographic(
    //     cartographic.longitude + Cesium.Math.toRadians(obj.offsetEast || 0),
    //     cartographic.latitude + Cesium.Math.toRadians(obj.offsetNorth || 0),
    //     cartographic.height + Cesium.Math.toRadians(obj.offsetHeight || 0)
    // );
    // let translation = Cesium.Cartesian3.subtract(
    //     Cesium.Cartographic.toCartesian (cartographic),
    //     Cesium.Cartographic.toCartesian (targetCartographic),
    //     new Cesium.Cartesian3()
    // );
    // obj.tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation)

    // 设置偏移距离(m)
    tileset.readyPromise.then(function(tileset) {
        let transform = Cesium.Transforms.eastNorthUpToFixedFrame(tileset.boundingSphere.center)
        let m = Cesium.Matrix4.setTranslation(Cesium.Matrix4.IDENTITY, new Cesium.Cartesian3(offsetEast || 0, offsetNorth || 0, offsetHeight || 0), new Cesium.Matrix4())
        let modelMatrix = Cesium.Matrix4.multiply(transform, m, transform)
        let target = new Cesium.Cartesian3()
        Cesium.Matrix4.getTranslation (modelMatrix, target)
        let translation = Cesium.Cartesian3.subtract(
            target,
            tileset.boundingSphere.center,
            new Cesium.Cartesian3()
        );
        tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation)
    })
}

function mergeObj (obj1, obj2) {
    const tilesOption = {...obj1}
    for(let key in obj2) {
        tilesOption[key] = obj1[key] ? obj1[key] :  obj2[key]
    }
    return tilesOption
}

function getUUId() {
    let tem = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    let id = "",
        len = tem.length,
        i = 0
    for (i; i < len; i++) {
        if (tem[i] == "-") id += tem[i]
        else {
            let num = Math.floor(Math.random() * 16)
            id += num.toString(16)
        }
    }
    return id
}